package au.csiro.nt.psdp.manager.Impl;

import au.csiro.nt.psdp.dao.UserDao;
import au.csiro.nt.psdp.manager.UserManager;
import au.csiro.nt.psdp.model.User;
import au.csiro.nt.psdp.model.Role;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.appfuse.service.UserExistsException;
import org.appfuse.service.impl.UniversalManagerImpl;
import org.springframework.dao.DataIntegrityViolationException;
import org.hibernate.exception.ConstraintViolationException;

import javax.persistence.EntityExistsException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.HashSet;


/**
 * Implementation of UserManager interface.</p>
 * <p/>
 * <p/>
 * <a href="UserManagerImpl.java.html"><i>View Source</i></a>
 * </p>
 *

 */
public class UserManagerImpl extends UniversalManagerImpl implements UserManager
{
    private UserDao dao;

    /**
     * Set the Dao for communication with the data layer.
     *
     * @param dao the UserDao that communicates with the database
     */
    public void setUserDao(UserDao dao)
    {
        this.dao = dao;
    }

    /**
     * @see org.appfuse.service.UserManager#getUser(java.lang.String)
     */
    public User getUser(String userId)
    {
        return dao.get(new Long(userId));
    }

    /**
     * @see org.appfuse.service.UserManager#getUsers(org.appfuse.model.User)
     */
    public List getUsers(User user)
    {
        return dao.getUsers();
    }
    
       public List getUsers(String userName){
       return dao.getUsers(userName);
   }
       
    public List getInstructors()
    {
        return dao.getInstructors();
    }
    /**
     * @see org.appfuse.service.UserManager#saveUser(org.appfuse.model.User)
     */
    public User saveUser(User user) throws UserExistsException
    {
        // if new user, lowercase userId
        if (user.getVersion() == null)
        {
            user.setUsername(user.getUsername().toLowerCase());
        }

        try
        {
            return dao.saveUser(user);
        }
        catch (DataIntegrityViolationException e)
        {
            throw new UserExistsException("User '" + user.getUsername() + "' already exists!");
        }
        catch (ConstraintViolationException e)
        {
            throw new UserExistsException("User '" + user.getUsername() + "' already exists!");
        }
        catch (EntityExistsException e)
        { // needed for JPA
            throw new UserExistsException("User '" + user.getUsername() + "' already exists!");
        }
    }

    public Set<User> bulkCreateUsers(String baseUsername, int numberOfUsers, String password, Set<Role> roles)
    {
        return bulkCreateUsers(baseUsername, 1, numberOfUsers, password, roles);
    }

    public Set<User> bulkCreateUsers(String baseUsername, int start, int numberOfUsers, String password, Set<Role> roles)
    {
        List<User> usersToAdd = new ArrayList<User>();
        for (int i = start; i <= numberOfUsers; i++)
        {
            User user = new User(baseUsername + i, password, roles, true);

            usersToAdd.add(user);
        }
        return saveUsers(usersToAdd);
    }

    public Set<User> bulkRemoveUsers(String baseName, int start, int end)
    {
        Set<User> removedUsers = new HashSet<User>();
        for (int i = start; i <= end; i++)
        {
            User user = getUserByUsername(baseName + i);
            removedUsers.add(user);
            removeUser(user);
        }
        return removedUsers;
    }

    public Set<User> saveUsers(List<User> users)
    {
        Set<User> savedUsers = new HashSet<User>();
        for (User user : users)
        {
            try
            {
                savedUsers.add(saveUser(user));
            }
            catch (UserExistsException e)
            {
                log.debug("SaveUsers: User '" + user.getUsername() + "' exists");
            }
        }
        return savedUsers;
    }

    /**
     * @see org.appfuse.service.UserManager#removeUser(java.lang.String)
     */
    public void removeUser(String userId)
    {
        log.debug("removing user: " + userId);
        dao.remove(new Long(userId));
    }

    public void removeUser(User user)
    {
        log.debug("removing user: " + user.getId());
        dao.removeUser(user);
    }

    public User getUserByUsername(String username) throws UsernameNotFoundException
    {
        return (User) dao.loadUserByUsername(username);
    }
}
